package com.uinnova.product.eam.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.exception.BinaryException;
import com.binary.jdbc.Page;
import com.uinnova.product.eam.constant.MeasureConstant;
import com.uinnova.product.eam.constant.MeasureFlowState;
import com.uinnova.product.eam.dao.MeasureEvaluateDao;
import com.uinnova.product.eam.dto.MeasureEvaluateDetailDto;
import com.uinnova.product.eam.dto.MeasureEvaluateDto;
import com.uinnova.product.eam.dto.MeasureEvaluateStatisticDto;
import com.uinnova.product.eam.dto.MeasureEvaluator;
import com.uinnova.product.eam.feign.workable.FlowableFeign;
import com.uinnova.product.eam.feign.workable.entity.TaskResponse;
import com.uinnova.product.eam.model.constants.FlowableConstant;
import com.uinnova.product.eam.model.es.ArchReviewInfo;
import com.uinnova.product.eam.model.es.MeasureConfDetail;
import com.uinnova.product.eam.model.es.MeasureEvaluate;
import com.uinnova.product.eam.model.es.MeasureFlowRecord;
import com.uinnova.product.eam.service.ArchReviewService;
import com.uinnova.product.eam.service.MeasureConfService;
import com.uinnova.product.eam.service.MeasureEvaluateService;
import com.uinnova.product.eam.service.MeasureFlowRecordService;
import com.uinnova.product.eam.vo.MeasureConfInfo;
import com.uinnova.product.eam.vo.MeasureEvaluateReq;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.query.CSysUser;
import com.uino.dao.util.ESUtil;
import com.uino.util.sys.SysUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Log4j2
public class MeasureEvaluateServiceImpl implements MeasureEvaluateService {

    @Autowired
    private MeasureEvaluateDao measureEvaluateDao;
    @Autowired
    private FlowableFeign flowableFeign;
    @Autowired
    private ArchReviewService archReviewService;
    @Autowired
    private MeasureFlowRecordService measureFlowRecordService;
    @Autowired
    private MeasureConfService measureConfService;
    @Autowired
    private IUserApiSvc userApiSvc;

    @Override
    public MeasureEvaluateDto detail(String taskId) {
        if (StringUtils.isBlank(taskId)) {
            throw new BinaryException("任务id不能为空");
        }
        MeasureEvaluateDto dto = new MeasureEvaluateDto(false);
        TaskResponse task = flowableFeign.getTaskInfoByTaskId(taskId);
        Assert.notNull(task, "未找到当前任务");
        //专家初审阶段的任务有度量评分 专家终审以及PMO阶段有度量统计
        if (!FlowableConstant.PRE_REVIEW_EXPERT.equals(task.getDescription())
                && !FlowableConstant.PRE_REVIEW_EXPERT_REJECT.equals(task.getDescription())
                && !FlowableConstant.PRE_REVIEW_FINAL_EXPERT.equals(task.getDescription())
                && !FlowableConstant.PMO_REVIEW.equals(task.getDescription())) {
            return dto;
        }
        //1.获取流程批次
        int flowBatch = getCurTaskFlowBatch(task);
        if (flowBatch == -1L) {
            return dto;
        }
        //2.获取流程度量记录
        Long archReviewId = Long.valueOf(task.getBusinessKey());
        MeasureFlowRecord measureFlowRecord = measureFlowRecordService.queryByArchReviewId(archReviewId, flowBatch);
        if (measureFlowRecord == null || !MeasureFlowState.MEASURE.equals(measureFlowRecord.getState())) {
            return dto;
        }
        //流程到达专家初审时的度量配置id
        Long measureConfId = measureFlowRecord.getMeasureConfId();
        //3.获取度量配置
        MeasureConfInfo measureConfInfo = measureConfService.info(measureConfId);
        //专家初审返测评信息
        if (FlowableConstant.PRE_REVIEW_EXPERT.equals(task.getDescription())
                || FlowableConstant.PRE_REVIEW_EXPERT_REJECT.equals(task.getDescription())) {
            setMeasureEvaluateInfo(task, flowBatch, dto, measureConfInfo);
            return dto;
        }
        //专家终审&&PMO返测评统计信息
        MeasureEvaluateStatisticDto statistic = getMeasureStatisticInfo(task.getProcessInstanceId(), flowBatch, measureConfInfo);
        dto.setIsNeedEvaluate(statistic != null && !CollectionUtils.isEmpty(statistic.getDetails()));
        dto.setStatistic(statistic);
        dto.setMeasureConfDesc(measureConfInfo.getDesc());
        return dto;
    }

    @Override
    public MeasureEvaluateDto detail(ArchReviewInfo archReviewInfo) {
        MeasureEvaluateDto dto = new MeasureEvaluateDto(false);
        //1.获取流程批次
        List<MeasureFlowRecord> measureFlowRecords = measureFlowRecordService.queryByArchReviewId(archReviewInfo.getId());
        int flowBatch = CollectionUtils.isEmpty(measureFlowRecords) ? 1 : measureFlowRecords.get(0).getFlowBatch();
        //2.获取流程度量记录
        MeasureFlowRecord measureFlowRecord = measureFlowRecordService.queryByArchReviewId(archReviewInfo.getId(), flowBatch);
        if (measureFlowRecord == null || !MeasureFlowState.MEASURE.equals(measureFlowRecord.getState())) {
            return dto;
        }
        //流程到达专家初审时的度量配置id
        Long measureConfId = measureFlowRecord.getMeasureConfId();
        //3.获取度量配置
        MeasureConfInfo measureConfInfo = measureConfService.info(measureConfId);
        //专家终审&&PMO返测评统计信息
        MeasureEvaluateStatisticDto statistic = getMeasureStatisticInfo(archReviewInfo.getProcessInstanceId(), flowBatch, measureConfInfo);
        dto.setIsNeedEvaluate(statistic != null && !CollectionUtils.isEmpty(statistic.getDetails()));
        dto.setStatistic(statistic);
        dto.setMeasureConfDesc(measureConfInfo.getDesc());
        return dto;
    }

    private void setMeasureEvaluateInfo(TaskResponse task, Integer flowBatch, MeasureEvaluateDto dto, MeasureConfInfo measureConfInfo) {
        //1.获取度量评分内容
        Map<Long, MeasureEvaluate> evaluateMap = getEvaluate(task, flowBatch);
        //2.当前任务绑定的初审专家领域&&分组---跟人没关系了(可能会转办)
        String group = getMeasureGroup(task);
        Long measureDomainId = getMeasureDomainId(task);
        if (StringUtils.isBlank(group) || measureDomainId == null) {
            return;
        }
        //3.组装结果
        dto.setMeasureConfId(measureConfInfo.getId());
        dto.setMeasureConfDesc(measureConfInfo.getDesc());
        List<MeasureEvaluateDetailDto> detailDtos = new ArrayList<>();
        for (MeasureConfDetail measureConfDetail : measureConfInfo.getDetails()) {
            List<MeasureEvaluator> evaluators = MeasureConstant.MEASURE_EVALUATOR_GROUP_A.equals(group) ?
                    measureConfDetail.getEvaluatorsA() : measureConfDetail.getEvaluatorsB();
            //无领域 || 当前任务领域不在此测评项 || 已办且未评的项
            if (CollectionUtils.isEmpty(evaluators)
                    || !evaluators.stream().map(MeasureEvaluator::getId).collect(Collectors.toSet()).contains(measureDomainId)
                    || (task.getTaskEndTime() != null && !evaluateMap.containsKey(measureConfDetail.getId()))) {
                continue;
            }

            MeasureEvaluateDetailDto detailDto = new MeasureEvaluateDetailDto();
            detailDto.setIndicatorClassify(measureConfDetail.getIndicatorClassify());
            detailDto.setIndicatorDesc(measureConfDetail.getIndicatorDesc());
            detailDto.setMaxScore(measureConfDetail.getMaxScore());
            detailDto.setMeasureConfDetailId(measureConfDetail.getId());
            detailDto.setProcessInstanceId(task.getProcessInstanceId());
            detailDto.setTaskId(task.getTaskId());
            detailDto.setFlowBatch(flowBatch);
            detailDto.setMeasureDomainId(measureDomainId);
            MeasureEvaluate evaluate = evaluateMap.get(measureConfDetail.getId());
            if (evaluate != null) {
                if (evaluate.getScore() != null) {
                    Double score = evaluate.getScore();
                    detailDto.setScore(Math.round(score * 10) / 10.0);
                }
                detailDto.setOpinion(evaluate.getOpinion());
                detailDto.setIsSubmit(evaluate.getIsSubmit());
            }
            detailDto.setIsStatistic(false);
            detailDtos.add(detailDto);
        }
        dto.setIsNeedEvaluate(!CollectionUtils.isEmpty(detailDtos));
        dto.setDetails(detailDtos);
    }

    private MeasureEvaluateStatisticDto getMeasureStatisticInfo(String processInstanceId, Integer flowBatch, MeasureConfInfo measureConfInfo) {
        MeasureEvaluateStatisticDto statisticDto = new MeasureEvaluateStatisticDto();
        List<MeasureEvaluateStatisticDto.MeasureRule> rules = new ArrayList<>();
        List<List<MeasureEvaluateStatisticDto.EvaluateDetail>> details = new ArrayList<>();
        List<MeasureEvaluateStatisticDto.EvaluateDetail> titles = new ArrayList<>();
        titles.add(new MeasureEvaluateStatisticDto.EvaluateDetail("评分领域", null, false));
        titles.add(new MeasureEvaluateStatisticDto.EvaluateDetail("评分人", null, false));
        Map<Long, MeasureEvaluator> measureEvaluatorMap = new HashMap<>();
        for (MeasureConfDetail measureConfDetail : measureConfInfo.getDetails()) {
            MeasureEvaluateStatisticDto.MeasureRule rule = new MeasureEvaluateStatisticDto.MeasureRule();
            rule.setMeasureConfDetailId(measureConfDetail.getId());
            rule.setIndicatorClassify(measureConfDetail.getIndicatorClassify());
            rule.setIndicatorDesc(measureConfDetail.getIndicatorDesc());
            rules.add(rule);
            titles.add(new MeasureEvaluateStatisticDto.EvaluateDetail(measureConfDetail.getIndicatorClassify(), null, false));
            if (!CollectionUtils.isEmpty(measureConfDetail.getEvaluatorsA())) {
                measureEvaluatorMap.putAll(measureConfDetail.getEvaluatorsA().stream()
                        .collect(Collectors.toMap(MeasureEvaluator::getId, Function.identity(), (k1,k2) -> k1)));
            }
            if (!CollectionUtils.isEmpty(measureConfDetail.getEvaluatorsB())) {
                measureEvaluatorMap.putAll(measureConfDetail.getEvaluatorsB().stream()
                        .collect(Collectors.toMap(MeasureEvaluator::getId, Function.identity(), (k1,k2) -> k1)));
            }
        }
        details.add(titles);
        statisticDto.setRules(rules);
        //测评信息
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("processInstanceId.keyword", processInstanceId));
        query.must(QueryBuilders.termQuery("flowBatch", flowBatch));
        query.must(QueryBuilders.termQuery("isStatistic", false));
        query.must(QueryBuilders.termQuery("isSubmit", true));
        Page<MeasureEvaluate> page = measureEvaluateDao.getSortListByQuery(1,3000, query, "createTime", false);
        List<MeasureEvaluate> measureEvaluates = page.getData();
        if (CollectionUtils.isEmpty(measureEvaluates)) {
            return null;
        }
        Map<String, Map<Long, MeasureEvaluate>> dataMap = new LinkedHashMap<>();
        Set<String> userLoginCodes = new HashSet<>();
        for (MeasureEvaluate evaluate : measureEvaluates) {
            String key = evaluate.getCreatorCode().concat("_").concat(evaluate.getMeasureDomainId().toString());
            Map<Long, MeasureEvaluate> userEvaluateMap = dataMap.getOrDefault(key, new HashMap<>());
            userEvaluateMap.put(evaluate.getMeasureConfDetailId(), evaluate);
            dataMap.put(key, userEvaluateMap);
            userLoginCodes.add(evaluate.getCreatorCode());
        }
        Map<String, SysUser> userMap = new HashMap<>();
        CSysUser cdt = new CSysUser();
        cdt.setLoginCodes(userLoginCodes.toArray(new String[userLoginCodes.size()]));
        List<SysUser> users = userApiSvc.getSysUserByCdt(cdt);
        if (!CollectionUtils.isEmpty(users)) {
            userMap = users.stream().collect(Collectors.toMap(SysUser::getLoginCode, Function.identity(), (k1,k2) -> k1));
        }
        for (Map.Entry<String, Map<Long, MeasureEvaluate>> entry : dataMap.entrySet()) {
            String[] key = entry.getKey().split("_");
            String userCode = key[0];
            Long measureDomainId = Long.parseLong(key[1]);
            Map<Long, MeasureEvaluate> evaluateMap = entry.getValue();
            List<MeasureEvaluateStatisticDto.EvaluateDetail> data = new ArrayList<>();
            String measureDomainName = measureDomainId.toString();
            if (measureEvaluatorMap.containsKey(measureDomainId)) {
                measureDomainName = measureEvaluatorMap.get(measureDomainId).getDomain();
            }
            data.add(new MeasureEvaluateStatisticDto.EvaluateDetail(measureDomainName, null, false));
            String userName = userCode;
            if (userMap.containsKey(userCode)) {
                userName = userMap.get(userCode).getUserName();
            }
            data.add(new MeasureEvaluateStatisticDto.EvaluateDetail(userName, null, false));
            for (MeasureConfDetail measureConfDetail : measureConfInfo.getDetails()) {
                String show = "-";
                String hideContent = null;
                MeasureEvaluate measureEvaluate = evaluateMap.get(measureConfDetail.getId());
                if (measureEvaluate != null) {
                    show = measureEvaluate.getScore().toString();
                    if (StringUtils.isNotBlank(measureEvaluate.getOpinion())) {
                        hideContent = measureEvaluate.getOpinion();
                    }
                }
                data.add(new MeasureEvaluateStatisticDto.EvaluateDetail(show, hideContent, false));
            }
            details.add(data);
        }
        //测评汇总信息
        BoolQueryBuilder statisticQuery = QueryBuilders.boolQuery();
        statisticQuery.must(QueryBuilders.termQuery("processInstanceId.keyword", processInstanceId));
        statisticQuery.must(QueryBuilders.termQuery("flowBatch", flowBatch));
        statisticQuery.must(QueryBuilders.termQuery("isStatistic", true));
        statisticQuery.must(QueryBuilders.termQuery("isSubmit", true));
        Page<MeasureEvaluate> statisticPage = measureEvaluateDao.getSortListByQuery(1,3000, statisticQuery, "createTime", false);
        List<MeasureEvaluate> statisticMeasureEvaluates = statisticPage.getData();
        if (CollectionUtils.isEmpty(statisticMeasureEvaluates)) {
            return null;
        }
        Map<Long, MeasureEvaluate> statisticMeasureEvaluateMap = statisticMeasureEvaluates.stream().collect(
                Collectors.toMap(MeasureEvaluate::getMeasureConfDetailId, Function.identity(), (k1,k2) -> k1));
        List<MeasureEvaluateStatisticDto.EvaluateDetail> statistic = new ArrayList<>();
        statistic.add(new MeasureEvaluateStatisticDto.EvaluateDetail("得分合计", null, true));
        double totalScore = statisticMeasureEvaluates.stream()
                .filter(m -> m.getScore() != null)
                .map(m -> BigDecimal.valueOf(m.getScore()))
                .reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue();
        statistic.add(new MeasureEvaluateStatisticDto.EvaluateDetail(changeTotalScore(totalScore), null, false));
        int totalMaxScore = measureConfInfo.getDetails().stream()
                .mapToInt(MeasureConfDetail::getMaxScore)
                .sum();
        //增加指标设置最高分-行
        List<MeasureEvaluateStatisticDto.EvaluateDetail> maxScoreList = new ArrayList<>();
        maxScoreList.add(new MeasureEvaluateStatisticDto.EvaluateDetail("指标设置最高分", null, false));
        maxScoreList.add(new MeasureEvaluateStatisticDto.EvaluateDetail(String.valueOf(totalMaxScore), null, false));
        for (MeasureConfDetail measureConfDetail : measureConfInfo.getDetails()) {
            String showName = "-";
            MeasureEvaluate statisticMeasureEvaluate = statisticMeasureEvaluateMap.get(measureConfDetail.getId());
            if (statisticMeasureEvaluate != null) {
                showName = changeTotalScore(statisticMeasureEvaluate.getScore());
            }
            statistic.add(new MeasureEvaluateStatisticDto.EvaluateDetail(showName, null, false));
            maxScoreList.add(new MeasureEvaluateStatisticDto.EvaluateDetail(String.valueOf(measureConfDetail.getMaxScore()), null, false));

        }
        details.add(maxScoreList);
        details.add(statistic);
        statisticDto.setDetails(details);
        statisticDto.setTotalMaxScore(totalMaxScore);
        statisticDto.setTotalScore(changeTotalScore(totalScore));
        return statisticDto;
    }

    private String changeTotalScore(Double score) {
        //精度不准
//        BigDecimal bigDecimal = new BigDecimal(score);
//        if (bigDecimal.scale() > 1) {
//            return score.toString();
//        }
//        return String.valueOf(score.intValue());

        DecimalFormat df = new DecimalFormat("#.#");
        return df.format(score);
    }

    private Integer getCurTaskFlowBatch(TaskResponse task) {
        //待办流程批次：取最新
        if (task.getTaskEndTime() == null) {
            Long archReviewId = Long.valueOf(task.getBusinessKey());
            List<MeasureFlowRecord> measureFlowRecords = measureFlowRecordService.queryByArchReviewId(archReviewId);
            return CollectionUtils.isEmpty(measureFlowRecords) ? 1 : measureFlowRecords.get(0).getFlowBatch();
        }
        //已办流程批次：取任务当时
        Map<String, Object> taskEchoVariables = task.getTaskEchoVariables();
        if (CollectionUtils.isEmpty(taskEchoVariables)
                || !taskEchoVariables.containsKey("flowBatch")
                || taskEchoVariables.get("flowBatch") == null) {
            return -1;
        }
        return Integer.parseInt(taskEchoVariables.get("flowBatch").toString());
    }

    private Map<Long, MeasureEvaluate> getEvaluate(TaskResponse task, Integer flowBatch) {
        //已办度量评分：处理任务时的评分
        if (task.getTaskEndTime() != null) {
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.termQuery("taskId.keyword", task.getTaskId()));
            query.must(QueryBuilders.termQuery("isStatistic", false));
            List<MeasureEvaluate> measureEvaluates = measureEvaluateDao.getListByQuery(query);
            return measureEvaluates.stream().collect(Collectors.toMap(
                    MeasureEvaluate::getMeasureConfDetailId, Function.identity(), (k1, k2) -> k1));
        }
        Long measureDomainId = getMeasureDomainId(task);
        if (measureDomainId == null) {
            return new HashMap<>();
        }
        //待办度量评分：当前流程当前批次当前领域里，当前人最后一次保存的评分
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("processInstanceId.keyword", task.getProcessInstanceId()));
        query.must(QueryBuilders.termQuery("flowBatch", flowBatch));
        query.must(QueryBuilders.termQuery("creatorCode.keyword", SysUtil.getCurrentUserInfo().getLoginCode()));
        query.must(QueryBuilders.termQuery("measureDomainId", measureDomainId));
        query.must(QueryBuilders.termQuery("isStatistic", false));
        Page<MeasureEvaluate> page = measureEvaluateDao.getSortListByQuery(1,3000, query, "createTime", false);
        List<MeasureEvaluate> measureEvaluates = page.getData();
        if (CollectionUtils.isEmpty(measureEvaluates)) {
            return new HashMap<>();
        }
        String lastTaskId = measureEvaluates.get(0).getTaskId();
        return measureEvaluates.stream()
                .filter(measureEvaluate -> lastTaskId.equals(measureEvaluate.getTaskId()))
                .collect(Collectors.toMap(MeasureEvaluate::getMeasureConfDetailId, Function.identity(), (k1,k2) -> k1));
    }

    private String getMeasureGroup(TaskResponse task) {
        Map<String, Object> taskEchoVariables = task.getTaskEchoVariables();
        Object childVariable = taskEchoVariables.get("childVariable");
        if (childVariable == null) {
            return null;
        }
        JSONObject json = JSON.parseObject(childVariable.toString());
        if (StringUtils.isBlank(json.getString("group"))) {
            return null;
        }
        return json.getString("group").replace("组", "");
    }

    private Long getMeasureDomainId(TaskResponse task) {
        Map<String, Object> taskEchoVariables = task.getTaskEchoVariables();
        Object childVariable = taskEchoVariables.get("childVariable");
        if (childVariable == null) {
            return null;
        }
        JSONObject json = JSON.parseObject(childVariable.toString());
        return json.getLong("domainId");
    }

    @Override
    public void save(MeasureEvaluateReq req) {
        if (req == null || StringUtils.isBlank(req.getTaskId())) {
            throw new BinaryException("任务id不能为空");
        }
        TaskResponse task = flowableFeign.getTaskInfoByTaskId(req.getTaskId());
        Assert.notNull(task, "未找到当前任务");
        if (task.getTaskEndTime() != null) {
            throw new BinaryException("任务已结束，不可评分");
        }
        //仅专家初审有度量评分
        if (!FlowableConstant.PRE_REVIEW_EXPERT.equals(task.getDescription())) {
            throw new BinaryException("非度量评分阶段");
        }
        if (CollectionUtils.isEmpty(req.getDetails())) {
            return;
        }
        //要不要评
        MeasureEvaluateDto measureEvaluateDto = detail(req.getTaskId());
        if (!measureEvaluateDto.getIsNeedEvaluate()
                || CollectionUtils.isEmpty(measureEvaluateDto.getDetails())) {
            throw new BinaryException("当前任务无需测评");
        }
        Long measureDomainId = getMeasureDomainId(task);
        if (measureDomainId == null) {
            return;
        }
        //可以评哪些
        Map<Long, MeasureEvaluateDetailDto> needMeasureConfDetailMap = measureEvaluateDto.getDetails().stream()
                .collect(Collectors.toMap(MeasureEvaluateDetailDto::getMeasureConfDetailId, Function.identity(), (k1,k2) -> k1));
        String curUserLoginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        List<MeasureEvaluate> measureEvaluates = new ArrayList<>();
        for (MeasureEvaluate measureEvaluate : req.getDetails()) {
            if (measureEvaluate.getScore() == null && StringUtils.isBlank(measureEvaluate.getOpinion())) {
                continue;
            }
            Assert.notNull(measureEvaluate.getMeasureConfDetailId(), "测评明细id不能为空");
            if (!needMeasureConfDetailMap.containsKey(measureEvaluate.getMeasureConfDetailId())) {
                throw new BinaryException("存在无需评审的明细，请刷新界面重试");
            }
            MeasureEvaluateDetailDto detailDto = needMeasureConfDetailMap.get(measureEvaluate.getMeasureConfDetailId());
            if (Boolean.TRUE.equals(detailDto.getIsSubmit())) {
                throw new BinaryException("测评内容已提交，不可修改");
            }
            if (measureEvaluate.getScore() != null) {
                if (measureEvaluate.getScore() < 0 || Double.compare(measureEvaluate.getScore(), detailDto.getMaxScore()) > 0)
                    throw new BinaryException("请输入0.0-" + detailDto.getMaxScore() + "数字");
            }
            MeasureEvaluate record = new MeasureEvaluate();
            record.setId(ESUtil.getUUID());
            record.setMeasureConfId(measureEvaluateDto.getMeasureConfId());
            record.setMeasureConfDetailId(measureEvaluate.getMeasureConfDetailId());
            record.setProcessInstanceId(task.getProcessInstanceId());
            record.setTaskId(req.getTaskId());
            record.setFlowBatch(getCurTaskFlowBatch(task));
            record.setMeasureDomainId(measureDomainId);
            record.setScore(measureEvaluate.getScore());
            record.setOpinion(measureEvaluate.getOpinion());
            record.setIsSubmit(false);
            record.setIsStatistic(false);
            record.setCreatorCode(curUserLoginCode);
            record.setCreateTime(ESUtil.getNumberDateTime());
            record.setModifierCode(curUserLoginCode);
            record.setModifyTime(ESUtil.getNumberDateTime());
            measureEvaluates.add(record);
        }
        if (CollectionUtils.isEmpty(measureEvaluates)) {
            return;
        }
        List<Long> measureConfDetailIds = measureEvaluates.stream().map(MeasureEvaluate::getMeasureConfDetailId).collect(Collectors.toList());
        BoolQueryBuilder deleteQuery = QueryBuilders.boolQuery();
        deleteQuery.must(QueryBuilders.termsQuery("measureConfDetailId", measureConfDetailIds));
        deleteQuery.must(QueryBuilders.termQuery("taskId.keyword", req.getTaskId()));
        deleteQuery.must(QueryBuilders.termQuery("creatorCode.keyword", curUserLoginCode));
        deleteQuery.must(QueryBuilders.termQuery("measureDomainId", measureDomainId));
        deleteQuery.must(QueryBuilders.termQuery("isStatistic", false));
        measureEvaluateDao.deleteByQuery(deleteQuery, true);

        measureEvaluateDao.saveOrUpdateBatch(measureEvaluates);
    }

    @Override
    public void submit(String taskId) {
        if (StringUtils.isBlank(taskId)) {
            throw new BinaryException("任务id不能为空");
        }
        TaskResponse task = flowableFeign.getTaskInfoByTaskId(taskId);
        Assert.notNull(task, "未找到当前任务");
        if (task.getTaskEndTime() != null) {
            throw new BinaryException("任务已结束，不可提交");
        }
        //仅专家初审有度量评分
        if (!FlowableConstant.PRE_REVIEW_EXPERT.equals(task.getDescription())) {
            throw new BinaryException("非度量评分阶段");
        }
        //要不要评
        MeasureEvaluateDto measureEvaluateDto = detail(taskId);
        if (!measureEvaluateDto.getIsNeedEvaluate()
                || CollectionUtils.isEmpty(measureEvaluateDto.getDetails())) {
            return;
        }
        //当前人当前任务下已保存的评分
        String curUserLoginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("taskId.keyword", taskId));
        query.must(QueryBuilders.termQuery("creatorCode.keyword", curUserLoginCode));
        query.must(QueryBuilders.termQuery("isStatistic", false));
        List<MeasureEvaluate> evaluates = measureEvaluateDao.getListByQuery(query);
        if (CollectionUtils.isEmpty(evaluates)) {
            throw new BinaryException("请完成所有指标度量评分后再进行提交");
        }
        Map<Long, MeasureEvaluate> evaluateMap = evaluates.stream().collect(
                Collectors.toMap(MeasureEvaluate::getMeasureConfDetailId, Function.identity(), (k1,k2) -> k1));
        for (MeasureEvaluateDetailDto evaluateDetail : measureEvaluateDto.getDetails()) {
            if (!evaluateMap.containsKey(evaluateDetail.getMeasureConfDetailId())) {
                throw new BinaryException("请完成所有指标度量评分后再进行提交");
            }
            MeasureEvaluate evaluate = evaluateMap.get(evaluateDetail.getMeasureConfDetailId());
            if (evaluate.getScore() == null) {
                throw new BinaryException("请完成所有指标度量评分后再进行提交");
            }
        }
        for (MeasureEvaluate evaluate : evaluates) {
            evaluate.setIsSubmit(true);
            evaluate.setModifierCode(curUserLoginCode);
            evaluate.setModifyTime(ESUtil.getNumberDateTime());
        }
        measureEvaluateDao.saveOrUpdateBatch(evaluates);
    }

    @Override
    public void statistic(String processInstanceId, String businessKey) {
        Long archReviewId = Long.valueOf(businessKey);
        List<MeasureFlowRecord> measureFlowRecords = measureFlowRecordService.queryByArchReviewId(archReviewId);
        int flowBatch = CollectionUtils.isEmpty(measureFlowRecords) ? 1 : measureFlowRecords.get(0).getFlowBatch();
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("processInstanceId.keyword", processInstanceId));
        query.must(QueryBuilders.termQuery("flowBatch", flowBatch));
        query.must(QueryBuilders.termQuery("isStatistic", false));
        query.must(QueryBuilders.termQuery("isSubmit", true));
        List<MeasureEvaluate> evaluates = measureEvaluateDao.getListByQuery(query);
        if (CollectionUtils.isEmpty(evaluates)) {
            return;
        }
        Map<Long, List<MeasureEvaluate>> groupMap = evaluates.stream().collect(
                Collectors.groupingBy(MeasureEvaluate::getMeasureConfDetailId));
        List<MeasureEvaluate> measureEvaluates = new ArrayList<>();
        Long measureConfId = evaluates.get(0).getMeasureConfId();
        for (Map.Entry<Long, List<MeasureEvaluate>> entry : groupMap.entrySet()) {
            Long measureConfDetailId = entry.getKey();
            double total = entry.getValue().stream()
                    .filter(m -> m.getScore() != null)
                    .map(m -> BigDecimal.valueOf(m.getScore()))
                    .reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue();
            double average = Math.round(total/entry.getValue().size() * 10) / 10.0;
            MeasureEvaluate record = new MeasureEvaluate();
            record.setId(ESUtil.getUUID());
            record.setMeasureConfId(measureConfId);
            record.setMeasureConfDetailId(measureConfDetailId);
            record.setProcessInstanceId(processInstanceId);
            record.setFlowBatch(flowBatch);
            record.setScore(average);
            record.setIsSubmit(true);
            record.setIsStatistic(true);
            record.setCreateTime(ESUtil.getNumberDateTime());
            record.setModifyTime(ESUtil.getNumberDateTime());
            measureEvaluates.add(record);
        }

        BoolQueryBuilder deleteQuery = QueryBuilders.boolQuery();
        deleteQuery.must(QueryBuilders.termQuery("processInstanceId.keyword", processInstanceId));
        deleteQuery.must(QueryBuilders.termQuery("flowBatch", flowBatch));
        deleteQuery.must(QueryBuilders.termQuery("isStatistic", true));
        measureEvaluateDao.deleteByQuery(deleteQuery, true);

        measureEvaluateDao.saveOrUpdateBatch(measureEvaluates);
    }
}
